package com.hrt.common.safe;

import com.btcode.common.AbstractSingleton;
import com.btcode.common.PropertiesUnit;
import com.btcode.db.result.Row;
import com.btcode.db.sqlparameter.SQLParameterList;
import com.btcode.exception.BusinessException;
import com.btcode.orm.model.IModel;
import com.btcode.security.RSAService;
import com.btcode.web.core.annotation.RequestMapping;
import com.btcode.web.core.respone.JsonRespone;
import com.btcode.web.core.respone.ResultFlag;
import com.btcode.web.core.unit.URLUtil;
import com.btcode.web.core.unit.WebContext;
import com.hrt.common.db.CommonDBManager;
import com.hrt.common.safe.exception.UserDisableException;
import com.hrt.common.safe.exception.VerifyCodeErrorException;
import com.hrt.common.safe.token.TokenService;
import com.hrt.common.systemmanager.systemsetting.register.CBcRegisterInfoModel;
import com.hrt.common.web.BaseController;
import com.hrt.common.web.RequestUnit;


import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.spec.InvalidKeySpecException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import javax.crypto.BadPaddingException;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.imageio.ImageIO;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
import java.util.UUID;

@RequestMapping(path = "/safe")
public class SafeController extends BaseController {

    @RequestMapping(path = "get-userinfo")
    public void getFunctions(ServletRequest arg0, ServletResponse arg1) throws IOException {

        IUser user = UserSessionManager.getInstance().getUser();

        if (user == null) {
            success("");
            return;
        }

        UserSafeService userService = UserSafeService.getInstance(UserSafeService.class);
        List<IModel> functions = userService.getUserFunction(user.getId());

        HashMap<String, Object> userInfo = new HashMap<>();
        userInfo.put("USER_ID", user.getId());
        userInfo.put("USER_NAME", user.getRealName());
        userInfo.put("USER_ACCOUNT", user.getAccount());
        userInfo.put("FUNCTIONS", functions);
        success(userInfo);
    }

    /**
     * 返回公钥，用于RAS加密登陆
     * @param arg0
     * @param arg1
     * @throws IOException
     */
    @RequestMapping(path = "get-public-key")
    public void getPublicKey(ServletRequest arg0, ServletResponse arg1) throws IOException {
       String publicKey = RSAService.getInstance().getPublicKeyBase64String();
       success(publicKey);
    }

    /**
     * 登陆，使用RAS加密
     * @param arg0
     * @param arg1
     * @throws IOException
     * @throws NoSuchPaddingException
     * @throws NoSuchAlgorithmException
     * @throws IllegalBlockSizeException
     * @throws BadPaddingException
     * @throws InvalidKeyException
     * @throws InvalidKeySpecException
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    @RequestMapping(path = "login")
    public void login(ServletRequest arg0, ServletResponse arg1)
        throws IOException, NoSuchPaddingException, NoSuchAlgorithmException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, InvalidKeySpecException {

        String username = RequestUnit.getString("username");
        String password = RequestUnit.getString("password");
        String platform = RequestUnit.getString("platform");
        String verifyCode = RequestUnit.getString("verifyCode");//验证码
        // 来自楠柏平台，需要判断离职情况
        if("nanbo".equals(platform)){
            String sql= "select t1.real_name as name, t2.ENTRY_STATUS, t1.tel\n" +
                    "  from c_bc_user t1\n" +
                    "  left join c_bc_staff t2 on t1.id = t2.user_id\n" +
                    " where t2.entry_status = '3' and t1.account=@username";
            SQLParameterList pc = new SQLParameterList();
            pc.put("username", username);
            List<Row> list =CommonDBManager.getDataExecuter().queryList(sql,pc);
            if(list.size()>0){
                throw new BusinessException("该员工已离职,不能登录。");
            }
        }
        //使用私钥解密
        password = RSAService.getInstance().decryptByPrivateKey(password);
        System.out.println("解密后的密码："+password);

        UserSafeService userService = UserSafeService.getInstance(UserSafeService.class);
        ResultFlag resultFlag = ResultFlag.SUCCESS;
        IUser user = null;
        String resultFlagDesc = "";
        HashMap<String, Object> data = new HashMap<>();
        CBcRegisterInfoModel cb=new CBcRegisterInfoModel();
        cb.setId(UUID.randomUUID().toString());
        cb.setCreateTime(new Date());
        //获取ip
        String ip=URLUtil.getIpAddr(arg0);
        try {

           //验证码，验证
            authVerifyCode(verifyCode,username);

            /**
             * 验证用户名密码
             */
            user = userService.getModelByLogin(username, password);
            /**
             * 设置session信息，用户兼容网页端session的方式
             */
            UserSessionManager.getInstance().setUser(user);
            /**
             * 如果走到这一步没有异常，就算成功
             */
            resultFlag = ResultFlag.SUCCESS;
            /**
             * 生成token
             */
            String token = TokenService.encode(user);
            /**
             * 作为参数传给前端
             */
            if (user instanceof HashMap) {
                data.putAll((HashMap) user);
            }
            else {
                data.put("USER_ID", user.getId());
                data.put("USER_NAME", user.getRealName());
                data.put("USER_ACCOUNT", user.getAccount());
            }
            cb.setUerId(user.getAccount());
            cb.setUserName(user.getRealName());
            cb.setStatus("登陆成功");
            //获取ip
            cb.setIp(ip);
            CommonDBManager.getORMExecuter().create(cb);
            data.put("token", token);
            /**
             * 处理登录前页面跳转信息
             */
            String lastUrl = RequestUnit.getString("url");

            if (lastUrl != null && !lastUrl.trim().equals("")) {
                data.put("url", lastUrl);
            }
        }
        catch (AccountNotExistException e) {
            resultFlag = ResultFlag.ERROR;
            resultFlagDesc = "登录失败";
            cb.setUerId(username);
            cb.setUserName(username);
            cb.setStatus("账号不存在");
            registerLoginInfo(cb,arg0);
            //账号不存在锁定ip
            LoginLock.setLogin(ip);
        }
        catch (PasswordErrorException e) {
            resultFlag = ResultFlag.ERROR;
            resultFlagDesc = "登录失败";
            cb.setUerId(username);
            cb.setUserName(username);
            cb.setStatus("密码错误");
            registerLoginInfo(cb,arg0);
            LoginLock.setLogin(username);
        }
        catch (UserDisableException e) {
            resultFlag = ResultFlag.ERROR;
            resultFlagDesc = "登录失败";
            cb.setUerId(username);
            cb.setUserName(username);
            cb.setStatus("用户停用");
            registerLoginInfo(cb,arg0);
            LoginLock.setLogin(username);
        }catch (VerifyCodeErrorException e) {
            resultFlag = ResultFlag.ERROR;
            resultFlagDesc = " 验证码错误";
            cb.setUerId(username);
            cb.setUserName(username);
            cb.setStatus(" 验证码错误");
            registerLoginInfo(cb, arg0);
            LoginLock.setLogin(username);
        }

        AbstractSingleton.getInstance(JsonRespone.class).outputObj(data, resultFlag,
                                                                   resultFlagDesc);

    }



    @RequestMapping(path = "logout")
    public void logout(ServletRequest arg0, ServletResponse arg1) throws IOException {
        IUser user = UserSessionManager.getInstance().getUser();
        CBcRegisterInfoModel cb=new CBcRegisterInfoModel();
        cb.setId(UUID.randomUUID().toString());
        cb.setCreateTime(new Date());
        cb.setUerId(user.getAccount());
        cb.setUserName(user.getRealName());
        cb.setStatus("注销成功");
        registerLoginInfo(cb,arg0);
        UserSessionManager.getInstance().clearUser();

        success("");
    }

    /**
     * 记录登陆信息
     * @param cb
     */
    private void registerLoginInfo(CBcRegisterInfoModel cb,ServletRequest arg0){
        //获取ip
        String ip=URLUtil.getIpAddr(arg0);
        cb.setIp(ip);
        CommonDBManager.getORMExecuter().create(cb);
    }
    @RequestMapping(path = "remove-lock-user")
    public void removeLockUser(ServletRequest arg0, ServletResponse arg1) throws IOException {
        String username = RequestUnit.getString("ACCOUNT");
        ResultFlag resultFlag = ResultFlag.SUCCESS;
        if(LoginLock.loginLocks.containsKey(username)){
            // 清除锁定账号
            LoginLock.loginLocks.remove(username);
            // 清除错误次数
            LoginLock.logins.remove(username);
        }
        AbstractSingleton.getInstance(JsonRespone.class).outputObj("", resultFlag,
            "");
    }

    @RequestMapping(path = "get-lock-user")
    public void getLockUser(ServletRequest arg0, ServletResponse arg1) throws IOException {
        Map<String, Date> locksUser = LoginLock.loginLocks;
        ResultFlag resultFlag = ResultFlag.SUCCESS;
        AbstractSingleton.getInstance(JsonRespone.class).outputObj(locksUser, resultFlag,
            "");
    }


    /***
     * 生成验证码
     * @param arg0
     * @param arg1
     * @throws IOException
     */
    @RequestMapping(path = "create-verify-code")
    public void createVerifyCode(ServletRequest arg0, ServletResponse arg1) throws IOException {
        try {
            HttpServletResponse response = WebContext.getResponse();
            //设置不缓存图片
            response.setHeader("Pragma", "No-cache");
            response.setHeader("Cache-Control", "No-cache");
            response.setDateHeader("Expires", 0);
            //指定生成的相应图片
            response.setContentType("image/jpeg");
            IdentifyingCode idCode = new IdentifyingCode();
            BufferedImage image = new BufferedImage(idCode.getWidth(), idCode.getHeight(), BufferedImage.TYPE_INT_BGR);
            Graphics2D g = image.createGraphics();
            //定义字体样式
            Font myFont = new Font("黑体", Font.BOLD, 25);
            //设置字体
            g.setFont(myFont);

            g.setColor(idCode.getRandomColor(200, 250));
            //绘制背景
            g.fillRect(0, 0, idCode.getWidth(), idCode.getHeight());

            g.setColor(idCode.getRandomColor(180, 200));
            idCode.drawRandomLines(g, 160);
            String verifyCode = idCode.drawRandomString(4, g);
            WebContext.getSession().setAttribute("verifyCode", verifyCode);//把验证码保存到session当中
            g.dispose();
            ImageIO.write(image, "JPEG", response.getOutputStream());
        } catch (Exception e) {
            throw new BusinessException("获取验证码出错");
        }

    }


    /**
     * 验证码，验证
     * verifyCode 验证码
     */
    public void authVerifyCode(String verifyCode,String username) throws VerifyCodeErrorException {
        PropertiesUnit.setPropertiesPath("/conf.properties");// 从配置文件获取验证码配置，判斷是否检测验证码
        String isOpenWhitesConf = PropertiesUnit.getValue("isOpenWhitesConf"); //是否开启白名单
        //白名单判断
        if (isOpenWhitesConf != null && !isOpenWhitesConf.equals("") && isOpenWhitesConf.equals("true")) {
            String sql= "select t2.id\n" +
                    "  from C_BC_USER_WHITES t2\n" +
                    "  left join c_bc_user  t1 on t1.id = t2.user_id\n" +
                    " where  t1.account=@username";
            SQLParameterList pc = new SQLParameterList();
            pc.put("username", username);
            List<Row> list =CommonDBManager.getDataExecuter().queryList(sql,pc);
            if(list.size()>0){
                //白名单里的用户，无需验证
                return;
            }
        }

        //验证码验证
        String isVerifyCodeConf = PropertiesUnit.getValue("isVerifyCodeConf");// 是否验证验证码：true 是， false 否
        if (isVerifyCodeConf != null && !isVerifyCodeConf.equals("") && isVerifyCodeConf.equals("true")) {
            String sessionVerifyCode = (String) WebContext.getSession().getAttribute("verifyCode");//session当中验证码
            if (sessionVerifyCode == null || sessionVerifyCode.equals("")) {
                throw new BusinessException(" 验证码解析异常");
            }
            if (verifyCode == null || verifyCode.equals("") || !verifyCode.equals(sessionVerifyCode)) {
                throw new VerifyCodeErrorException("验证码错误");
            }
        }
    }

    /***
     *  从配置文件获取验证码配置
     * @param arg0
     * @param arg1
     * @throws IOException
     */
    @RequestMapping(path = "get-verify-code-conf")
    public void getVerifyCodeConf(ServletRequest arg0, ServletResponse arg1) throws IOException {
        PropertiesUnit.setPropertiesPath("/conf.properties");// 从配置文件获取验证码配置，判斷是否检测验证码
        String isVerifyCodeConf = PropertiesUnit.getValue("isVerifyCodeConf");// 是否验证验证码：true 是， false 否
        success(isVerifyCodeConf);
    }

}
